package com.lb.activity.service.impl;

import cn.hutool.core.date.DateUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lb.activity.mapper.ExamineFlowStepMapper;
import com.lb.activity.mapper.PurchaseApplyDetailMapper;
import com.lb.activity.mapper.PurchaseApplyMapper;
import com.lb.activity.po.*;
import com.lb.activity.service.PurchaseApplyService;
import com.lb.activity.util.JsonUtil;
import com.lb.activity.util.ResultUtil;
import com.lb.activity.util.SessionUtil;
import com.lb.activity.util.SnowflakeIdWorker;
import com.lb.activity.util.emumdata.PurchaseStepEnum;
import com.lb.activity.vo.PurchaseApplyDetailVo;
import com.lb.activity.vo.PurchaseApplyVo;
import com.lb.activity.vo.PurchaseRunningProcess;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 采购接口实现
 * @author liubin
 */
@Service
public class PurchaseApplyServiceImpl implements PurchaseApplyService {

    @Autowired
    private PurchaseApplyMapper purchaseApplyMapper;

    @Autowired
    private PurchaseApplyDetailMapper purchaseApplyDetailMapper;
    
    @Autowired
    private SnowflakeIdWorker idWorker;

    @Autowired
    private IdentityService identityservice;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private ExamineFlowStepMapper examineFlowStepMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil add(PurchaseApplyVo purchaseApplyVo) {
        User sessionUser = SessionUtil.getSessionUser();
        if(sessionUser != null){
            long id = idWorker.nextId();
            BigDecimal totalMoney = new BigDecimal(0);
            String[] goodsName = purchaseApplyVo.getGoodsName();
            BigDecimal[] goodsPrice = purchaseApplyVo.getGoodsPrice();
            Long[] goodsNum = purchaseApplyVo.getGoodsNum();
            for (int i = 0; i < goodsName.length; i++) {
                totalMoney = totalMoney.add(goodsPrice[i]);
                PurchaseApplyDetail detail = PurchaseApplyDetail.builder()
                        .id(idWorker.nextId())
                        .applyId(id)
                        .goodsName(goodsName[i])
                        .goodsPrice(goodsPrice[i])
                        .goodsNum(goodsNum[i])
                        .build();
                purchaseApplyDetailMapper.insertSelective(detail);
            }
            PurchaseApply apply = PurchaseApply.builder()
                    .id(id)
                    .deptId(purchaseApplyVo.getDeptId())
                    .deptName(purchaseApplyVo.getDeptName())
                    .proposer(sessionUser.getUserNameCn())
                    .proposerId(sessionUser.getId())
                    .totalMoney(totalMoney)
                    .currentStep(PurchaseStepEnum.PROCUREMENT_MANAGER.getCurrentStep())
                    .build();
            purchaseApplyMapper.insertSelective(apply);
            //插入步骤
            ExamineFlowStep step = ExamineFlowStep.builder()
                    .id(idWorker.nextId())
                    .workId(id)
                    .stepUser(sessionUser.getUserNameCn())
                    .stepUserId(sessionUser.getId())
                    .stepName("申请")
                    .stepSuggest("同意")
                    .build();
            examineFlowStepMapper.insertSelective(step);
            //使用 主键作为businesskey,连接业务数据和流程数据
            String businesskey=String.valueOf(apply.getId());
            identityservice.setAuthenticatedUserId(sessionUser.getId()+"");
            Map<String,Object> variables=new HashMap<String, Object>();
            variables.put("starter", sessionUser.getId());
            //开始流程
            ProcessInstance instance = runtimeService.startProcessInstanceByKey("purchase",businesskey,variables);
        }
        return ResultUtil.ok();
    }

    @Override
    public ResultUtil myPurchase(PurchaseApplyVo purchaseApplyVo) {
        Integer limit = purchaseApplyVo.getLimit();
        Integer page = purchaseApplyVo.getPage()-1;
        String userid =  SessionUtil.getSessionUser().getId()+"";
        ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery();
        int total = Integer.parseInt(query.processDefinitionKey("purchase").involvedUser(userid).count()+"");
        List<ProcessInstance> purchases = query.processDefinitionKey("purchase").involvedUser(userid).listPage(page, limit);
        List<PurchaseRunningProcess> list = new ArrayList<PurchaseRunningProcess>();
        for (ProcessInstance purchase : purchases) {
            PurchaseRunningProcess process = new PurchaseRunningProcess();
            if(purchase.getActivityId()==null){
                //有子流程
                String father = purchase.getProcessInstanceId();
                //子流程的活动节点
                String sonactiveid = runtimeService.createExecutionQuery().parentId(father).singleResult().getActivityId();
                String sonexeid = runtimeService.createExecutionQuery().parentId(father).singleResult().getId();
                process.setActivityid(sonactiveid);
                System.out.println(taskService.createTaskQuery().executionId(sonexeid).singleResult().getName());
            }else{
                process.setActivityid(purchase.getActivityId());
            }
            PurchaseApply apply = purchaseApplyMapper.selectByPrimaryKey(purchase.getBusinessKey());
            BeanUtils.copyProperties(apply, process);
            process.setBusinesskey(purchase.getBusinessKey());
            process.setExecutionid(purchase.getId());
            process.setProcessInstanceId(purchase.getProcessInstanceId());
            process.setApplyDateStr(DateUtil.formatDate(apply.getCreateTime()));
            process.setProposer(apply.getProposer());
            if (apply.getProposerId().equals(Long.parseLong(userid))) {
                list.add(process);
            }else {
                continue;
            }

        }
        return ResultUtil.build(0, "", total, list);
    }

    @Override
    public ResultUtil myPurchaseAll(PurchaseApplyVo purchaseApplyVo) {
        PageHelper.startPage(purchaseApplyVo.getPage(),purchaseApplyVo.getLimit());
        List<PurchaseApply> applys = purchaseApplyMapper.selectAll();
        PageInfo<PurchaseApply> pageInfo = new PageInfo<>(applys);
        return ResultUtil.build(0, "", Integer.parseInt(pageInfo.getTotal()+""), applys);
    }

    @Override
    public ResultUtil procurement(PurchaseApplyVo purchaseApplyVo) {
        List<PurchaseRunningProcess> results = new ArrayList<>();
        String type = purchaseApplyVo.getType();
        List<Task> tasks = new ArrayList<>();
        int total = 0;
        if("procurement".equals(type)){
            tasks = taskService.createTaskQuery().taskCandidateGroup("采购经理").listPage(purchaseApplyVo.getPage() - 1, purchaseApplyVo.getLimit());
            total = taskService.createTaskQuery().taskCandidateGroup("采购经理").list().size();
        }else if("finance".equals(type)){
            tasks = taskService.createTaskQuery().taskCandidateGroup("财务审批").listPage(purchaseApplyVo.getPage() - 1, purchaseApplyVo.getLimit());
            total = taskService.createTaskQuery().taskCandidateGroup("财务审批").list().size();
        }else if("chuna".equals(type)){
            tasks = taskService.createTaskQuery().taskCandidateGroup("出纳员").listPage(purchaseApplyVo.getPage() - 1, purchaseApplyVo.getLimit());
            total = taskService.createTaskQuery().taskCandidateGroup("出纳员").list().size();
        }else if("generalManager".equals(type)){
            tasks = taskService.createTaskQuery().taskCandidateGroup("总经理").listPage(purchaseApplyVo.getPage() - 1, purchaseApplyVo.getLimit());
            total = taskService.createTaskQuery().taskCandidateGroup("总经理").list().size();
        }
        for (Task task : tasks) {
            String instanceid = task.getProcessInstanceId();
            ProcessInstance ins = runtimeService.createProcessInstanceQuery().processInstanceId(instanceid).singleResult();
            String businesskey = ins.getBusinessKey();

            PurchaseApply apply = purchaseApplyMapper.selectByPrimaryKey(Long.parseLong(businesskey));
            PurchaseRunningProcess process = new PurchaseRunningProcess();

            BeanUtils.copyProperties(apply, process);
            process.setApplyDateStr(DateUtil.formatDate(apply.getCreateTime()));
            // 赋值
            process.setTaskId(task.getId());
            process.setProcessInstanceId(task.getProcessInstanceId());
            process.setTaskName(task.getName());
            process.setProcessdefId(task.getProcessDefinitionId());
            process.setTaskCreateTime(task.getCreateTime());
            results.add(process);

        }
        return ResultUtil.build(0,"",total,results);
    }

    @Override
    public ResultUtil procurementDetail(String taskId) {
        PurchaseApplyVo purchaseApplyVo = new PurchaseApplyVo();
        PurchaseApply apply = getOne(taskId);
        Example example = new Example(PurchaseApplyDetail.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("applyId",apply.getId());
        List<PurchaseApplyDetail> details = purchaseApplyDetailMapper.selectByExample(example);
        List<PurchaseApplyDetailVo> purchaseApplyDetailVos = JsonUtil.listOtherList(details, PurchaseApplyDetailVo.class);
        BeanUtils.copyProperties(apply,purchaseApplyVo);
        purchaseApplyVo.setList(purchaseApplyDetailVos);
        return ResultUtil.ok(purchaseApplyVo);
    }

    PurchaseApply getOne(String taskId){
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        ProcessInstance process = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId())
                .singleResult();
        PurchaseApply apply = purchaseApplyMapper.selectByPrimaryKey(Long.parseLong(process.getBusinessKey()));
        return apply;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil procurementDeal(String taskId, String approve) {
        User sessionUser = SessionUtil.getSessionUser();
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("purchaseauditi", approve);
        PurchaseApply apply = getOne(taskId);
        if("true".equals(approve)){
            apply.setCurrentStep(PurchaseStepEnum.FINANCIAL_APPLY.getCurrentStep());
            ExamineFlowStep step = ExamineFlowStep.builder()
                    .id(idWorker.nextId())
                    .workId(apply.getId())
                    .stepUser(sessionUser.getUserNameCn())
                    .stepUserId(sessionUser.getId())
                    .stepName("采购部门经理")
                    .stepSuggest("同意")
                    .build();
            examineFlowStepMapper.insertSelective(step);
        }else{
            ExamineFlowStep step = ExamineFlowStep.builder()
                    .id(idWorker.nextId())
                    .workId(apply.getId())
                    .stepUser(sessionUser.getUserNameCn())
                    .stepUserId(sessionUser.getId())
                    .stepName("采购部门经理")
                    .stepSuggest("拒绝")
                    .build();
            examineFlowStepMapper.insertSelective(step);
            apply.setCurrentStep(PurchaseStepEnum.ADJUST_APPLY.getCurrentStep());
        }
        purchaseApplyMapper.updateByPrimaryKeySelective(apply);
        taskService.claim(taskId, sessionUser.getId()+"");
        taskService.complete(taskId, variables);
        return ResultUtil.ok();
    }

    @Override
    public ResultUtil financeDeal(String taskId, String approve) {
        User sessionUser = SessionUtil.getSessionUser();
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("finance", approve);
        PurchaseApply apply = getOne(taskId);
        if("true".equals(approve)){
            variables.put("money", apply.getTotalMoney());
            if( apply.getTotalMoney().compareTo(new BigDecimal(10000)) > 0){
                apply.setCurrentStep(PurchaseStepEnum.GENERAL_MANAGER_APPLY.getCurrentStep());
            }else{
                apply.setCurrentStep(PurchaseStepEnum.PAYMENT_APPLY.getCurrentStep());
            }
            ExamineFlowStep step = ExamineFlowStep.builder()
                    .id(idWorker.nextId())
                    .workId(apply.getId())
                    .stepUser(sessionUser.getUserNameCn())
                    .stepUserId(sessionUser.getId())
                    .stepName("财务")
                    .stepSuggest("同意")
                    .build();
            examineFlowStepMapper.insertSelective(step);
        }else{
            ExamineFlowStep step = ExamineFlowStep.builder()
                    .id(idWorker.nextId())
                    .workId(apply.getId())
                    .stepUser(sessionUser.getUserNameCn())
                    .stepUserId(sessionUser.getId())
                    .stepName("财务")
                    .stepSuggest("拒绝")
                    .build();
            examineFlowStepMapper.insertSelective(step);
            apply.setCurrentStep(PurchaseStepEnum.FINANCIAL_REFUSE_APPLY.getCurrentStep());
        }
        purchaseApplyMapper.updateByPrimaryKeySelective(apply);
        taskService.claim(taskId, sessionUser.getId()+"");
        taskService.complete(taskId, variables);
        return ResultUtil.ok();
    }

    @Override
    public ResultUtil chunaDeal(String taskId) {
        User sessionUser = SessionUtil.getSessionUser();
        PurchaseApply apply = getOne(taskId);

        apply.setCurrentStep(PurchaseStepEnum.RECEIPT_CONFIRMATION_APPLY.getCurrentStep());
        ExamineFlowStep step = ExamineFlowStep.builder()
                .id(idWorker.nextId())
                .workId(apply.getId())
                .stepUser(sessionUser.getUserNameCn())
                .stepUserId(sessionUser.getId())
                .stepName("出纳")
                .stepSuggest("已付款")
                .build();
        examineFlowStepMapper.insertSelective(step);

        purchaseApplyMapper.updateByPrimaryKeySelective(apply);
        taskService.claim(taskId, sessionUser.getId()+"");
        taskService.complete(taskId);
        return ResultUtil.ok();
    }

    @Override
    public ResultUtil pendingReceipt(PurchaseApplyVo purchaseApplyVo) {
        Integer limit = purchaseApplyVo.getLimit();
        Integer page = purchaseApplyVo.getPage()-1;
        String userid =  SessionUtil.getSessionUser().getId()+"";
        TaskQuery taskQuery = taskService.createTaskQuery().processDefinitionKey("purchase").taskCandidateOrAssigned(userid).taskDefinitionKey("receiveitem");
        long total = taskQuery.count();
        List<Task> tasks = taskQuery.listPage(page, limit);
        List<PurchaseRunningProcess> list = new ArrayList<PurchaseRunningProcess>();
        for (Task task : tasks) {
            String instanceid = task.getProcessInstanceId();
            ProcessInstance ins = runtimeService.createProcessInstanceQuery().processInstanceId(instanceid).singleResult();
            String businesskey = ins.getBusinessKey();

            PurchaseApply apply = purchaseApplyMapper.selectByPrimaryKey(Long.parseLong(businesskey));
            PurchaseRunningProcess process = new PurchaseRunningProcess();

            BeanUtils.copyProperties(apply, process);
            process.setApplyDateStr(DateUtil.formatDate(apply.getCreateTime()));
            // 赋值
            process.setTaskId(task.getId());
            process.setProcessInstanceId(task.getProcessInstanceId());
            process.setTaskName(task.getName());
            process.setProcessdefId(task.getProcessDefinitionId());
            process.setTaskCreateTime(task.getCreateTime());
            list.add(process);
        }
        return ResultUtil.build(0, "", Integer.parseInt(total+""), list);
    }

    @Override
    public ResultUtil takeGood(String taskId) {
        String userid =  SessionUtil.getSessionUser().getId()+"";
        PurchaseApply one = getOne(taskId);
        one.setCurrentStep(PurchaseStepEnum.END.getCurrentStep());
        purchaseApplyMapper.updateByPrimaryKeySelective(one);
        taskService.claim(taskId, userid);
        taskService.complete(taskId);
        return null;
    }

    @Override
    public ResultUtil myPurchaseAgain(PurchaseApplyVo purchaseApplyVo) {
        Integer limit = purchaseApplyVo.getLimit();
        Integer page = purchaseApplyVo.getPage()-1;
        String userid =  SessionUtil.getSessionUser().getId()+"";
        TaskQuery taskQuery = taskService.createTaskQuery().processDefinitionKey("purchase").taskCandidateOrAssigned(userid).taskDefinitionKey("updateapply");
        long total = taskQuery.count();
        List<Task> tasks = taskQuery.listPage(page, limit);
        List<PurchaseRunningProcess> list = new ArrayList<PurchaseRunningProcess>();
        for (Task task : tasks) {
            String instanceid = task.getProcessInstanceId();
            ProcessInstance ins = runtimeService.createProcessInstanceQuery().processInstanceId(instanceid).singleResult();
            String businesskey = ins.getBusinessKey();

            PurchaseApply apply = purchaseApplyMapper.selectByPrimaryKey(Long.parseLong(businesskey));
            PurchaseRunningProcess process = new PurchaseRunningProcess();

            BeanUtils.copyProperties(apply, process);
            process.setApplyDateStr(DateUtil.formatDate(apply.getCreateTime()));
            // 赋值
            process.setTaskId(task.getId());
            process.setProcessInstanceId(task.getProcessInstanceId());
            process.setTaskName(task.getName());
            process.setProcessdefId(task.getProcessDefinitionId());
            process.setTaskCreateTime(task.getCreateTime());
            list.add(process);
        }
        return ResultUtil.build(0, "", Integer.parseInt(total+""), list);
    }

    @Override
    public ResultUtil purchaseAgain(String taskId,String approve) {
        User sessionUser = SessionUtil.getSessionUser();
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("updateapply", approve);
        PurchaseApply apply = getOne(taskId);
        if("true".equals(approve)){
            apply.setCurrentStep(PurchaseStepEnum.PROCUREMENT_MANAGER.getCurrentStep());
            ExamineFlowStep step = ExamineFlowStep.builder()
                    .id(idWorker.nextId())
                    .workId(apply.getId())
                    .stepUser(sessionUser.getUserNameCn())
                    .stepUserId(sessionUser.getId())
                    .stepName("重新提交")
                    .stepSuggest("已重新提交")
                    .build();
            examineFlowStepMapper.insertSelective(step);
        }else{
            ExamineFlowStep step = ExamineFlowStep.builder()
                    .id(idWorker.nextId())
                    .workId(apply.getId())
                    .stepUser(sessionUser.getUserNameCn())
                    .stepUserId(sessionUser.getId())
                    .stepName("重新提交")
                    .stepSuggest("已取消")
                    .build();
            examineFlowStepMapper.insertSelective(step);
            apply.setCurrentStep(PurchaseStepEnum.END.getCurrentStep());
        }
        purchaseApplyMapper.updateByPrimaryKeySelective(apply);
        taskService.claim(taskId, sessionUser.getId()+"");
        taskService.complete(taskId, variables);
        return ResultUtil.ok();
    }

    @Override
    public ResultUtil generalManagerDeal(String taskId,String approve) {
        User sessionUser = SessionUtil.getSessionUser();
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("manager", approve);
        PurchaseApply apply = getOne(taskId);
        if("true".equals(approve)){
            apply.setCurrentStep(PurchaseStepEnum.PAYMENT_APPLY.getCurrentStep());
            ExamineFlowStep step = ExamineFlowStep.builder()
                    .id(idWorker.nextId())
                    .workId(apply.getId())
                    .stepUser(sessionUser.getUserNameCn())
                    .stepUserId(sessionUser.getId())
                    .stepName("总经理")
                    .stepSuggest("同意")
                    .build();
            examineFlowStepMapper.insertSelective(step);
        }else{
            ExamineFlowStep step = ExamineFlowStep.builder()
                    .id(idWorker.nextId())
                    .workId(apply.getId())
                    .stepUser(sessionUser.getUserNameCn())
                    .stepUserId(sessionUser.getId())
                    .stepName("总经理")
                    .stepSuggest("拒绝")
                    .build();
            examineFlowStepMapper.insertSelective(step);
            apply.setCurrentStep(PurchaseStepEnum.END.getCurrentStep());
        }
        purchaseApplyMapper.updateByPrimaryKeySelective(apply);
        taskService.claim(taskId, sessionUser.getId()+"");
        taskService.complete(taskId, variables);
        return ResultUtil.ok();
    }

    @Override
    public ResultUtil purchaseDetail(Long id) {
        PurchaseApplyVo purchaseApplyVo = new PurchaseApplyVo();
        PurchaseApply apply = purchaseApplyMapper.selectByPrimaryKey(id);
        Example example = new Example(PurchaseApplyDetail.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("applyId",apply.getId());
        List<PurchaseApplyDetail> details = purchaseApplyDetailMapper.selectByExample(example);
        List<PurchaseApplyDetailVo> purchaseApplyDetailVos = JsonUtil.listOtherList(details, PurchaseApplyDetailVo.class);
        BeanUtils.copyProperties(apply,purchaseApplyVo);
        purchaseApplyVo.setList(purchaseApplyDetailVos);
        return ResultUtil.ok(purchaseApplyVo);
    }


}
